/*;
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package mp3organizer;

import com.mpatric.mp3agic.ID3v1;
import com.mpatric.mp3agic.ID3v2;
import com.mpatric.mp3agic.InvalidDataException;
import com.mpatric.mp3agic.Mp3File;
import com.mpatric.mp3agic.UnsupportedTagException;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Aderthad
 */
public class Mp3Orginizer {

    /**
     * @param args the command line arguments
     */
    private static final List<Album> albums = new ArrayList<>();

    private static Actionable action;

    private static final File folder = new File("e:\\Temp\\");

    public static void main(String[] args) throws IOException, UnsupportedTagException, InvalidDataException {

        action = new RenameSongs();

        StringBuilder sb = new StringBuilder();

        final List<Path> mp3s = new ArrayList<>();

        Files.walkFileTree(getFolder().toPath(), new FileVisitor<Path>() {

            @Override
            public FileVisitResult preVisitDirectory(Path t, BasicFileAttributes bfa) throws IOException {
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path t, BasicFileAttributes bfa) throws IOException {
                if (t.toString().endsWith(".mp3")) {
                    mp3s.add(t);
                } else if (t.toString().endsWith(".url") || t.toString().endsWith(".db")) {
                    t.toFile().delete();
                }

                return FileVisitResult.CONTINUE;

            }

            @Override
            public FileVisitResult visitFileFailed(Path t, IOException ioe) throws IOException {
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path t, IOException ioe) throws IOException {
                return FileVisitResult.CONTINUE;
            }
        });

        for (Path mp3 : mp3s) {
            Mp3File mp3file = new Mp3File(mp3.toString());

            String name = "";
            String albumName = "";
            String track = "";
            ID3v1 iD3v1Tag = null;
            ID3v2 iD3v2Tag = null;

            if (mp3file.hasId3v2Tag()) {
                iD3v2Tag = mp3file.getId3v2Tag();

                name = iD3v2Tag.getTitle() == null ? "" : iD3v2Tag.getTitle();
                albumName = iD3v2Tag.getAlbum() == null ? "_UNSORTED" : iD3v2Tag.getAlbum();
                track = iD3v2Tag.getTrack();
            } else if (mp3file.hasId3v1Tag()) {
                iD3v1Tag = mp3file.getId3v1Tag();

                name = iD3v1Tag.getTitle();
                albumName = iD3v1Tag.getAlbum();
                track = iD3v1Tag.getTrack();

            } else {
                sb.append(mp3 + "\n");
            }

            name = normalize(name);
            albumName = normalize(albumName);

            if (track == null || track.isEmpty()) {
                track = "1";
            }

            int index = track.indexOf("/");
            track = (index == -1) ? track : track.substring(0, index);

            Song song = new Song(mp3, track, name);

            Album a = getAlbum(albumName);

            a.addSong(song);
            System.out.println(mp3);
        }

        if (albums.size() > 0) {
            action.work(albums);
        }

        System.out.println(sb.toString());

    }

    private static String normalize(String s) {
        return s.replaceAll(":", "-")
                .replaceAll("\\?", "")
                .replaceAll("/", "")
                .replaceAll("\\.", "")
                .replaceAll("\"", "'")
                .replaceAll("\\*", "_")
                .trim();
    }

    private static Album getAlbum(String s) {
        for (Album a : albums) {
            if (s.equals(a.getName())) {
                return a;
            }
        }
        Album album = new Album(s);
        albums.add(album);
        return album;

    }

    /**
     * @return the folder
     */
    public static File getFolder() {
        return folder;

    }

    public static class Song {

        public Song(Path path, String trackNum, String name) {
            this.path = path;
            this.trackNum = trackNum;
            this.name = name;
        }

        private Path path;
        private String trackNum;
        private String name;
        private ID3v1 iD3v1Tag = null;
        private ID3v2 iD3v2Tag = null;

        /**
         * @return the path
         */
        public Path getPath() {
            return path;
        }

        /**
         * @param path the path to set
         */
        public void setPath(Path path) {
            this.path = path;
        }

        /**
         * @return the trackNum
         */
        public String getTrackNum() {
            return trackNum;
        }

        /**
         * @param trackNum the trackNum to set
         */
        public void setTrackNum(String trackNum) {
            this.trackNum = trackNum;
        }

        /**
         * @return the name
         */
        public String getName() {
            return name;
        }

        /**
         * @param name the name to set
         */
        public void setName(String name) {
            this.name = name;
        }

        /**
         * @return the iD3v1Tag
         */
        public ID3v1 getiD3v1Tag() {
            return iD3v1Tag;
        }

        /**
         * @param iD3v1Tag the iD3v1Tag to set
         */
        public void setiD3v1Tag(ID3v1 iD3v1Tag) {
            this.iD3v1Tag = iD3v1Tag;
        }

        /**
         * @return the iD3v2Tag
         */
        public ID3v2 getiD3v2Tag() {
            return iD3v2Tag;
        }

        /**
         * @param iD3v2Tag the iD3v2Tag to set
         */
        public void setiD3v2Tag(ID3v2 iD3v2Tag) {
            this.iD3v2Tag = iD3v2Tag;
        }
    }

    public static class Album {

        private String name;

        private List<Song> songs = new ArrayList<>();

        public Album(String s) {
            name = s;
        }

        protected void addSong(Song song) {
            getSongs().add(song);
        }

        /**
         * @return the path
         */
        public String getName() {
            return name;
        }

        /**
         * @param path the path to set
         */
        public void setName(String path) {
            this.name = path;
        }

        /**
         * @return the songs
         */
        public List<Song> getSongs() {
            return songs;
        }
    }
}
